package cn.leon.mysocket;

import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

import okhttp3.CertificatePinner;
import okio.Buffer;

/**
 * Created by leon on 2019/8/10.
 */
public class SSLClient {

    public static X509TrustManager getTrustManager() {
        return new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                //                try {
                //                    for (X509Certificate certificate : chain) {
                //                        certificate.checkValidity(); //检查证书是否过期，签名是否通过等
                //                    }
                //                } catch (Exception e) {
                //                    throw new CertificateException(e);
                //                }
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
    }

    public static HostnameVerifier getHostnameVerifier() {
        return new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                return true;
            }
        };
    }

    /**
     * SSL Pinning 获取证书
     * 方法一：OkHttp提供了一个 CertificatePinner 类可以方便的设置 SSL Pinning
     * 使用：httpClient.certificatePinner(pinner)
     *
     * @return certificata
     */
    public static CertificatePinner getCertificata(String url) {

        Certificate ca = null;

        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");

            try (InputStream caInput = getCerInputStream(CER_PEM)) {
                ca = cf.generateCertificate(caInput);
            }
        } catch (CertificateException | IOException e) {
            e.printStackTrace();
        }

        String certPin = "";
        if (ca != null) {
            certPin = CertificatePinner.pin(ca);
        }

        return new CertificatePinner.Builder()
                .add(url, certPin)
                .build();
    }

    /**
     * 方法二：创建一个只信任指定CA证书的 SSLSocketFactory 对象，注入到OkHttp中。这样OkHttp
     * 会使用注入的SSLSocketFactory去创建SSL Socket了
     * 使用：httpClient.sslSocketFactory(sslFactory, trustManager)
     */
    public static SSLSocketFactory getSSLSocketFactory() {
        SSLSocketFactory sslSocketFactory = null;
        try {
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            Certificate ca = null;
            try (InputStream caInput = getCerInputStream(CER_PEM)) {
                ca = certificateFactory.generateCertificate(caInput);
            } catch (CertificateException e) {
                e.printStackTrace();
            }

            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            if (ca == null) {
                return null;
            }
            keyStore.setCertificateEntry("ca", ca);

            String algorithm = TrustManagerFactory.getDefaultAlgorithm();
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
            trustManagerFactory.init(keyStore);

            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
            sslSocketFactory = sslContext.getSocketFactory();

        } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        return sslSocketFactory;
    }


    public static InputStream getCerInputStream(String pem) {
        Buffer buffer = new Buffer();
        buffer.writeUtf8(pem);
        return buffer.inputStream();
    }

    public static String CER_PEM = "-----BEGIN CERTIFICATE-----\n" +
            "MIIFWDCCBECgAwIBAgISBLR/S5U+66UqqcEvxRDFYFtAMA0GCSqGSIb3DQEBCwUA\n" +
            "MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD\n" +
            "ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA3MTIwMzE0MTJaFw0x\n" +
            "OTEwMTAwMzE0MTJaMBsxGTAXBgNVBAMMECouaW5yb2JvdC5jb20uY24wggEiMA0G\n" +
            "CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDtr/kipeci3YyyM2eENRpqUVCfhUl+\n" +
            "IKsE5XgBlvRCqXr8ZNSOQdFheXw8C1OzbMjmmQktV3KnKhFoQawnr8SeuSkSyRjg\n" +
            "i5v+Kggx2qxmz8GkN2B5ArziVoavQk1F9kYj7Yx13dkF8n0TI3c+KRlA+4L+CCEx\n" +
            "hteiybl2IO45yU+D2gaUYtZWs+22vLndMAV7x/RpqTqkK/eZafTrGcw2gi2tb57Q\n" +
            "J2nmaVWsZT6LdIRDTNwCoEv4JSNG4vB4ngyr7UqzGyYZafeUHbvk8/l3JSEoEsNf\n" +
            "fI4bGNKxF39ymHCCzmWdJqd2T/0BSmG9CtAGwo2byRI2YYRjJ5tbaEazAgMBAAGj\n" +
            "ggJlMIICYTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG\n" +
            "AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFLVJ54uE3/Xyj6IRNNs73itR\n" +
            "+bb0MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEB\n" +
            "BGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0\n" +
            "Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0\n" +
            "Lm9yZy8wGwYDVR0RBBQwEoIQKi5pbnJvYm90LmNvbS5jbjBMBgNVHSAERTBDMAgG\n" +
            "BmeBDAECATA3BgsrBgEEAYLfEwEBATAoMCYGCCsGAQUFBwIBFhpodHRwOi8vY3Bz\n" +
            "LmxldHNlbmNyeXB0Lm9yZzCCAQQGCisGAQQB1nkCBAIEgfUEgfIA8AB2AG9Tdqwx\n" +
            "8DEZ2JkApFEV/3cVHBHZAsEAKQaNsgiaN9kTAAABa+RjeB0AAAQDAEcwRQIhAPuR\n" +
            "EIItfgW4Ja1mz83YZFr554YD0YrMgjElPkngZlY6AiA5hmoPADsx169GilJv8gSx\n" +
            "PJORAPKjqbZeALcE0hdiYQB2AGPy283oO8wszwtyhCdXazOkjWF3j711pjixx2hU\n" +
            "S9iNAAABa+Rjd/kAAAQDAEcwRQIgeTUzYQa4xxMCUujBENeXF+MzZoFypMJf/k1e\n" +
            "wT7uMzgCIQC5omvpUQwOI8yCKwR3fRTGmOinypj+SQtJR60BaC4iqzANBgkqhkiG\n" +
            "9w0BAQsFAAOCAQEAJGalotxkikXs8qn12QclgdXpIYQN//yzD2BT9NTpiT6NoSk9\n" +
            "/C5lHFRzZelxOcDUtYiwGZrCcM62UV5TtDL4ut8aaQyCSStuc6/iDuzuwkYx7/tB\n" +
            "uW2Bl+QjV8xSfiMFSYpfEW+XZwynx1bYMRyibQTbH2Qly4ov01U0YbGwoyPX45va\n" +
            "mYLpvd3+Ike/dDkRJCzgF22FqZA/tx4UJVu/9G8ptYoqn53jlzIc+9Un4VF5C5nr\n" +
            "sE1SLo9Wb9F5Ky1HxKVM1hVSR6+jk1Gu7PWl0OgcUDjpBJ55fNaXJ7SsVjWPU8t4\n" +
            "WuU8NGXjXZtvFV8jDIIc4KIi5aOzMu3cHHJSSg==\n" +
            "-----END CERTIFICATE-----\n";

    public static String PRI_PEM = "-----BEGIN PRIVATE KEY-----\n" +
            "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDtr/kipeci3Yyy\n" +
            "M2eENRpqUVCfhUl+IKsE5XgBlvRCqXr8ZNSOQdFheXw8C1OzbMjmmQktV3KnKhFo\n" +
            "Qawnr8SeuSkSyRjgi5v+Kggx2qxmz8GkN2B5ArziVoavQk1F9kYj7Yx13dkF8n0T\n" +
            "I3c+KRlA+4L+CCExhteiybl2IO45yU+D2gaUYtZWs+22vLndMAV7x/RpqTqkK/eZ\n" +
            "afTrGcw2gi2tb57QJ2nmaVWsZT6LdIRDTNwCoEv4JSNG4vB4ngyr7UqzGyYZafeU\n" +
            "Hbvk8/l3JSEoEsNffI4bGNKxF39ymHCCzmWdJqd2T/0BSmG9CtAGwo2byRI2YYRj\n" +
            "J5tbaEazAgMBAAECggEAXAswXEWIy4ymJoAXjzANSayxnwS7oBdAgwXlwh/V+Vau\n" +
            "ZL0bPveoAKpN/OaaBDqVVg9faWqa4Lc+xHPiGgBMEPc9O6QaeSI3R2a5g6zd5HaB\n" +
            "03kKZ/IyeSfuwkHXsMcdBF7CbQZ7O31bCCVM0QqTWAHOCVfWmtpP+R9LLb604jUe\n" +
            "+ETxwhAHTx3cZoFgub3OXWtN5oK2aitxZiabduq1gQPQ2admBUEl3yZcMEhmVyx4\n" +
            "Sd44KkpmhzSNEW1481DpLqsx4xPFmZhSKBZHZbYF1KkiZSg2q6cJG5hZg2jo7Zhs\n" +
            "gYviHtGoZxG0jDQxhHqO4dpbqsNM0ztVyZ7Yrf64KQKBgQD8GyrKOp67k1VMq1UZ\n" +
            "NJp7FZeIlXX2Un7LWd3L/Q9rXBazMcCIxRZ4Q1loV1BTZqlEAkOUNZuGxjGMfVXH\n" +
            "Vi+q0BDewKsqpA/AVgA1zkmcBNoheBqB2PQHgyTWKlcL9AGSewfnEEmjvcVqVAdF\n" +
            "aGBVtL3xYcM2UVqjOVQILYBMBwKBgQDxW8tJoqCNzgpBalOSdv2eN8/lDBYqmSKA\n" +
            "AV7kmDzzYYNLn7j5h9JNRmuOAMIEQTikBZ5ELKibQcwqe4hQqGYqlfvobc5Mue9t\n" +
            "J2o9wRKHYbM3ye2BPzh6I8aLBNYDkCrk6PnACd/wA3Jl6UhrVgbkWgO/Y5T9GyR2\n" +
            "+iYGEAtc9QKBgQCHaghH68jLNE5DClyBV3IK3wQwByf/kTwt+i1anqkjn6lJw1WJ\n" +
            "oWN6YaKqmwu4YJJWx2iJOWo6sEZ5EfF7St37wBrvq0nFc65KP2eJfy6msSyBgcOr\n" +
            "L1+UkWq95qwu7XfSuGb8RBFp9EsP2+az72afYqAMAdkbWgN3XRm38sjRDQKBgQCj\n" +
            "nIA/2FhSCFv3YCZq4PKnsFnjgL/9/HTgpQ04lOKscWvZddqkfKfY7mW2i1j6HWRR\n" +
            "++T/fe6F4KKQIdGUK7OmJqnvM5BnfpuJOPDSD/GJiHc+2EmCFeMpGNtcHdkd7TrG\n" +
            "lg/HWGpPf2arIuqOqHBfl412zgCPWzjq1kO0VGf/iQKBgQDw65l90LY/vBMfX0ya\n" +
            "vijYpnN6orIO0RhPBx1DEQekEdBVW2m79ba/GGR93TeJS8seXk25Tael+8sUdUg3\n" +
            "daeeS96gxZDXn5baTASgPWbB6wyE/wNm8J1qYHY8yw3KOF9SGjSOW5aRJrXDx0rB\n" +
            "Cn2D4/HlImoNIL8OwaIUeM3zcg==\n" +
            "-----END PRIVATE KEY-----\n";
}